<?php
/*
	Aurus CMS - free OOP CMS
	Copyright (C) 2010  Nestor Yanchuk

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('ROOT')) die();
class Users implements Core {
	/**
	 * Return an instance of class
	 *
	 * @return Users
	 */
	public static function getInstance(){
		return Factory::get(__CLASS__);
	}
	
    /**
     * MySQL class link
     *
     * @var object
     * @see class Mysql
     */
    private $mysql = null;

    /**
     * Aurus class link
     *
     * @var object
     */
    private $aurus = null;
    private $cache = null;

    private $is_logged = false;
    private $is_admin = false;

    private $user_data = array();
    private $defaultGroup = 3;
    private $userGroups = array();

    private $usersById = array();
    private $usersByName = array();

    public $noavatar = '';
    public $USERGROUPDATA = array();

    
	function __construct() {
        $this->aurus = Aurus::getInstance();
        $this->mysql = Mysql::getInstance();

        $this->checkLogged();
        $this->noavatar = Config::get('noavatar', 'class_users');
    }

    /**
     * Log in user
     *
     * @param string $user
     * @param string $pass
     */
    function logIn($user, $pass) {
        $user1 = $this->mysql->escape($user);
        $pass = md5(md5($pass));
        $user = $this->mysql->getarray("SELECT COUNT(*) AS count FROM " . PREFIX . "_users WHERE login='{$user1}' AND password='{$pass}'");
 
        
        if ((int) $user['count'] > 0) {
            $this->mysql->query('UPDATE '.PREFIX.'_users SET last_visit=last_login,last_login='.TIME.' WHERE login="'.$user1.'" AND password="'.$pass.'"');
            set_cookie('au_user', $user1);
            set_cookie('au_pass', $pass );
            $this->aurus->location(LINK_ROOT);
            return true;
        }
        return false;
    }

    public function is_logged() {
        return $this->is_logged;
    }

    public function is_admin() {
        return $this->is_admin;
    }

    /**
     * Log out user
     */
    function logOut() {

        set_cookie('au_user', '', -1);
        set_cookie('au_pass', '', -1);
        $_SESSION = array();
        session_destroy();
        $this->aurus->location(LINK_ROOT);
    }

    /**
     * Register user
     * Return user id or -1 if name is bad or -2 if user with that login exists
     * @param string $login
     * @param string $pass
     * @param string $email
     * @param string $icq
     * @param string $land
     * @param string $signature
     * @param string $about
     * @return user id if OK, -1 if name is not valid, -2 if already registrated user with the same name
     */
    function registerUser($login, $pass, $email, $icq, $land, $signature, $about) {
        if (!$this->isValidName($login)) {
            return -1;
        }
        if ($this->check_exist($login, $email)) {
            return -2;
        }
        if (!isValidEmail($email)) {
            return -3;
        }
        $pass = md5(md5($pass));
        $email = trim(strtolower($email));
        $email = $this->mysql->escape($email);
        $icq = $this->mysql->escape($icq);
        $land = $this->mysql->escape($land);
        $signature = $this->mysql->escape($signature);
        $signature = $this->mysql->escape($signature);
        $about = $this->mysql->escape($about);

        $this->mysql->insert('users', array('login' => $login, 'password' => $pass, 'email' => $email, 'icq' => $icq, 'group' => $this->defaultGroup, 'country' => $land, 'signature' => $signature, 'about' => $about, 'reg_date' => TIME));
        //$this->mysql->query("INSERT INTO " . PREFIX . "_users ('login','password','email','icq','country','signature','about','group') VALUES ('{$login}','{$pass}','{$email}','{$icq}','{$land}','{$signature}','{$about}','{$this->defaultGroup}')");
        return mysql_insert_id();
    }

    /**
     * Check if user exists
     *
     * @param string $login
     * @param string $email
     * @return true, if user exists; else - false
     */
    function check_exist($login, $email = false) {
        if ($email !== false) {
            $email = strtolower($email);
            $sql = "email='{$email}' OR ";
        } else  $sql = '';
        $login = strtolower($login);
        $strtr_a = array('e' => '[eеё]', 'r' => '[rг]', 't' => '[tт]', 'y' => '[yу]', 'u' => '[uи]', 'i' => '[i1l!]', 'o' => '[oо0]', 'p' => '[pр]', 'a' => '[aа]', 's' => '[s5]', 'w' => 'w', 'q' => 'q', 'd' => 'd', 'f' => 'f', 'g' => '[gд]', 'h' => '[hн]', 'j' => 'j', 'k' => '[kк]', 'l' => '[l1i!]', 'z' => 'z', 'x' => '[xх%]', 'c' => '[cс]', 'v' => '[vuи]', 'b' => '[bвь]', 'n' => '[nпл]', 'm' => '[mм]', 'й' => '[йиu]', 'ц' => 'ц', 'у' => '[уy]', 'е' => '[еeё]', 'н' => '[нh]', 'г' => '[гr]', 'ш' => '[шwщ]', 'щ' => '[щwш]', 'з' => '[з3э]', 'х' => '[хx%]', 'ъ' => '[ъь]', 'ф' => 'ф', 'ы' => '(ы|ь[i1l!]?)', 'в' => '[вb]', 'а' => '[аa]', 'п' => '[пn]', 'р' => '[рp]', 'о' => '[оo0]', 'л' => '[лn]', 'д' => 'д', 'ж' => 'ж', 'э' => '[э3з]', 'я' => '[я]', 'ч' => '[ч4]', 'с' => '[сc]', 'м' => '[мm]', 'и' => '[иuй]', 'т' => '[тt]', 'ь' => '[ьb]', 'б' => '[б6]', 'ю' => '(ю|[!1il][oо0])', 'ё' => '[ёеe]', '1' => '[1il!]', '2' => '2', '3' => '[3зэ]', '4' => '[4ч]', '5' => '[5s]', '6' => '[6б]', '7' => '7', '8' => '8', '9' => '9', '0' => '[0оo]', '_' => '_', '#' => '#', '%' => '[%x]', '^' => '[^~]', '(' => '[(]', ')' => '[)]', '=' => '=', '.' => '[.]', '-' => '-', '[' => '[\[]');
        $sname = strtr($login, $strtr_a);
        $count = $this->mysql->getarray("SELECT COUNT(*) as count FROM " . PREFIX . "_users WHERE {$sql} LOWER(login) REGEXP '[[:<:]]{$login}[[:>:]]' OR login = '{$login}'");

        if ((int) $count['count'] > 0) {
            return true;
        }
        return false;
    }

    /**
     * Check name
     *
     * @param unknown_type $name
     * @return true,if name valid
     */
    function isValidName($name) {
        if (strlen($name) < 4 or strlen($name) > 15) {
            return false;
        }
        $bedarr = array( "'", '"', '@', '/', '\\', '&', '`');
        foreach ($bedarr as $s) {
            if (!is_bool(strpos($name, $s))) {
                return false;
            }
        }
        return true;
    }

    /**
     * Get user data by login or id
     *
     * @param string $dname
     * @param int $id
     * @param string $login
     * @return mixed
     */
    function getUserData($dname, $id = false, $login = false) {
        if ($id) {
            if (isset($this->usersById[$id])) {
                return $this->usersById[$id][$dname];
            }
            $this->usersById[$id] = $this->mysql->getarray("SELECT * FROM `" . PREFIX . "_users` WHERE `uid`={$id}");
            return $this->usersById[$id][$dname];
        } elseif ($login) {
            if (isset($this->usersByName[$login])) {
                return $this->usersByName[$login][$dname];
            }

            $this->usersByName[$login] = $this->mysql->getarray("SELECT * FROM `" . PREFIX . "_users` WHERE `login`='{$login}'");
            return $this->usersByName[$login][$dname];
        }
    }

    /**
     * Get data for current user.
     *
     * @param string $dataname
     * @return mixed
     */
    function getLoggedUsersData($dataname) {
        if ($this->is_logged) {
            return stripslashes($this->user_data[$dataname]);
        } else {
            $unlogged = array('uid' => false, 'login' => false, 'password' => false, 'email' => false, 'icq' => false, 'group' => 4, 'reg_date' => false, 'country' => false, 'signature' => false, 'about' => false, 'pm_count' => 0, 'unr_pm_count' => 0, 'news_count' => 0, 'com_count' => 0, 'topic_count' => 0, 'avatar' => '', 'last_login' => false, 'custom_data' => '');
            return $unlogged[$dataname];
        }
        return false;
    }

    /**
     * Check if user logged in
     * @return null or false if user is not logged in
     */
    public function checkLogged() {
        if (isset($_COOKIE['au_user']) && isset($_COOKIE['au_pass'])) {
            $dbdata = $this->mysql->getarray("SELECT * FROM " . PREFIX . "_users WHERE login='{$this->mysql->escape($_COOKIE['au_user'])}' AND password='{$this->mysql->escape($_COOKIE['au_pass'])}'");
            if ($dbdata['login'] == $_COOKIE['au_user'] && $dbdata['password'] == $_COOKIE['au_pass']) {
                $this->is_logged = true;
                $this->user_data = $dbdata;
                if ((int) $dbdata['group'] == 1) {
                    $this->is_admin = true;
                }
            }
        }
        
        return false;
    }

    /**
     * Gets list of usergroups
     *
     */
    function getUserGroups() {
        if (Cache::exists('usergroups')) {
            $this->userGroups = Cache::get('usergroups');
        } else {
            $mg = $this->mysql->query("SELECT * FROM `" . PREFIX . "_usergroups`");
            while ($e = $this->mysql->fetch_assoc($mg)) {
                $p[$e['gid']] = unserialize($e['groupallow']);
            }
            Cache::set('usergroups', $p);
            $this->userGroups = Cache::get('usergroups');
        }
        return $this->userGroups;
    }

    /**
     * Check user permission.
     *
     * @param int $group
     * @param string $canDo
     * @return true if user can $canDo, else - false
     */
    function can($group, $canDo) {
        if (!count($this->userGroups)) {
            $this->getUserGroups();
        }
        if (!isset($this->userGroups[$group][$canDo])) {
            return false;
        }
        return boolean($this->userGroups[$group][$canDo]);
    }

    /**
     * Adds setting for usergroup settings
     *
     * @param string $name
     * @param string $desc
     * @param string $fieldtype, can be "input" or "select" or "textarea"
     * @param array(key => value) $vars
     */
    function addUsergroupPermission($name, $desc, $fieldtype, $vars = array()) {
        $this->USERGROUPDATA[$name] = array($desc, $fieldtype, $vars);
    }

    function getGroupData($name, $groupId, $bool = false) {
        if (!count($this->userGroups)) {
            $this->getUserGroups();
        }
        if (!isset($this->userGroups[$groupId][$name])) {
            return false;
        }
        if ($bool) {
            return boolean($this->userGroups[$groupId][$name]);
        } else {
            return $this->userGroups[$groupId][$name];
        }
    }
}